package controller.transform;

import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;

import javax.media.j3d.Transform3D;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;

import math.Transforms;

import component.AbstractComponent;
import component.Status;
import component.Tube;
import component.group.FindAxis;

public class RotateAxisMode extends RotateMode {

	private Tube axis;
	
	private Vector3d rotationAxis;
	private Point3d rotationPoint;
	
	private int lastX = 0;
	
	public RotateAxisMode(Gui gui, Scene scene, Tube axis) {
		super(gui, scene);

		this.axis = axis;
		
		border = new FindAxis().find(axis);
		markAxis();
		gui.lockCamera();
		this.setDefaultHelp();
		this.setupAxisAndPoint();
	}
	
	private void setupAxisAndPoint() {
		rotationPoint = axis.getPos();
		rotationAxis = axis.getOrientation().getVector();
		if (axis.getPos().distance(gui.getCameraPosition()) > axis.getPos().distance(gui.getCameraPosition())) {
			rotationAxis.negate();
		}
	}
	
	private void markAxis() {
		border.setStatusFlag(Status.HIGHLIGHTED, true);
	}
	
	private void unmarkAxis() {
		border.setStatus(Status.NORMAL);
	}

	@Override
	public TransformMode mousePressed(MouseEvent e) {
		if (e.getButton() == MouseEvent.BUTTON3) {
			this.unmarkAxis();
			return new InitMode(gui, scene);
		}
		transformHistory.setIdentity();
		AbstractComponent component = scene.pickClosest(e);
		if (!border.contains(component)) {
			selectComponent(component);
		}
		lastX = e.getX();
		
		return this;
	}

	@Override
	public TransformMode mouseReleased(MouseEvent e) {
		if (grabbedSelection != null) {
			if (!grabbedSelection.isValidPosition()) {
				undo();
			} else {
				scene.connectPossible();
			}
		}
		unselectComponent();
		this.setDefaultHelp();
		return this;
	}

	@Override
	public TransformMode mouseMoved(MouseEvent e) {
		return this;
	}

	@Override
	public TransformMode mouseDragged(MouseEvent e) {
		if (grabbedSelection == null) return this;
		if (grabbedSelection.containsLockedComponents())
			return this;
		int deltaX = e.getX() - lastX;
		lastX = e.getX();
		
		Transform3D transform = Transforms.makeAxisRotation(rotationPoint, rotationAxis, deltaX);
		grabbedSelection.applyTransform(transform);
		transformHistory.mul(transform, transformHistory);
		
		if (grabbedSelection.isValidPosition()) {
			this.setLegalGroupState();
		} else {
			this.setIllegalGroupState();
		}

		return this;
	}

	@Override
	public TransformMode keyPressed(KeyEvent e) {
		return this;
	}

	@Override
	public TransformMode keyReleased(KeyEvent e) {
		return this;
	}

	@Override
	public void deselected() {
		unmarkAxis();
		gui.unlockCamera();
	}

}
